home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / gnu / oleo_src.lha / src / busi.c next >
C/C++ Source or Header  |  1992-07-27  |  9KB  |  497 lines

  1. /*    Copyright (C) 1990 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20. #include "sysdef.h"
  21.  
  22. #include "global.h"
  23. #include "cell.h"
  24. #include "eval.h"
  25. #include "errors.h"
  26.  
  27. struct value {
  28.     int    type;
  29.     union vals x;
  30. };
  31.  
  32. #define Float    x.c_d
  33. #define String    x.c_s
  34. #define Int    x.c_l
  35. #define Value    x.c_i
  36. #define Rng    x.c_r
  37.  
  38. static double
  39. pmt FUN3(double,principal, double,rate, double,term)
  40. {
  41.     return (principal * rate)/ ( 1 - pow(1+rate,-(term)));
  42. }
  43.  
  44.  
  45. static int
  46. npv FUN3(struct rng *,rng, double,rate, double *,putres)
  47. {
  48.     double npv;
  49.     int i;
  50.     double f;
  51.     CELL *cell_ptr;
  52.     char *strptr;
  53.  
  54.     find_cells_in_range(rng);
  55.     for(i=1,npv=0.0;cell_ptr=next_cell_in_range();i++) {
  56.         switch(GET_TYP(cell_ptr)) {
  57.         case 0:
  58.             f=0.0;
  59.             goto know_f;
  60.  
  61.         case TYP_INT:
  62.             f=(double)(cell_ptr->cell_int);
  63.             goto know_f;
  64.  
  65.         case TYP_FLT:
  66.             f=cell_ptr->cell_flt;
  67.             goto know_f;
  68.  
  69.         case TYP_STR:
  70.             strptr=cell_ptr->cell_str;
  71.             f=astof(&strptr);
  72.             if(*strptr)
  73.                 return NON_NUMBER;
  74.         know_f:
  75.             npv+=f * (1.0/(pow(1.0+rate,(double)i)));
  76.             break;
  77.  
  78.         case TYP_ERR:
  79.             return cell_ptr->cell_err;
  80.  
  81.         default:
  82.             return NON_NUMBER;
  83.         }
  84.     }
  85.  
  86.     *putres = npv;
  87.     return 0;
  88. }
  89.  
  90. static void
  91. do_pmt FUN1(struct value *,p)
  92. {
  93.     p->Float=pmt(p->Float,(p+1)->Float,(p+2)->Float);
  94. }
  95.  
  96. static void
  97. do_pv FUN1(struct value *,p)
  98. {
  99.     double    payment,
  100.         interest,
  101.         term;
  102.  
  103.     payment=p[0].Float;
  104.     interest=p[1].Float;
  105.     term=p[2].Float;
  106.  
  107.     p->Float=payment * ((1 - pow(1+interest,-term))/ interest);
  108. }
  109.  
  110. static void
  111. do_npv FUN1(struct value *,p)
  112. {
  113.     int tmp;
  114.  
  115.     tmp=npv(&(p->Rng),(p+1)->Float,&(p->Float));
  116.     if(tmp) {
  117.         p->Value=tmp;
  118.         p->type=TYP_ERR;
  119.     }
  120.     p->type=TYP_FLT;
  121. }
  122.  
  123. static void
  124. do_irr FUN1(struct value *,p)
  125. {
  126.     double try;
  127.     double res;
  128.     double mint,maxt;
  129.     double minr,maxr;
  130.     int i;
  131.     int tmp;
  132.  
  133.     minr=maxr=0;
  134.     mint=maxt=0;
  135.     while(minr>=0) {
  136.         mint+=1;
  137.         tmp=npv(&(p->Rng),mint,&minr);
  138.         if(tmp)    {
  139.             p->Value=tmp;
  140.             p->type=TYP_ERR;
  141.             return;
  142.         }
  143.     }
  144.     while(maxr<=0) {
  145.         maxt-=1;
  146.         tmp=npv(&(p->Rng),maxt,&maxr);
  147.         if(tmp) {
  148.             p->Value=tmp;
  149.             p->type=TYP_ERR;
  150.             return;
  151.         }
  152.     }
  153.     try=(p+1)->Float;
  154.     for(i=0;;i++) {
  155.         if(i==40) {
  156.             p->Value=BAD_INPUT;
  157.             p->type=TYP_ERR;
  158.             return;
  159.         }
  160.         tmp=npv(&(p->Rng),try,&res);
  161.         if(tmp) {
  162.             p->Value=tmp;
  163.             p->type=TYP_ERR;
  164.             return;
  165.         }
  166.         if(fabs(res*1000000.0)<1)
  167.             break;
  168.         if(res>0) {
  169.             maxt=try;
  170.             maxr=res;
  171.         } else if(res<0) {
  172.             mint=try;
  173.             minr=res;
  174.         }
  175.         if(minr/-10>maxr) {
  176.             /* it is quite near maxt */
  177.             try=(maxt*10+mint)/11;
  178.         } else if(minr/-2>maxr) {
  179.             try=(maxt*2+mint)/3;
  180.         } else if(minr*-10<maxr) {
  181.             /* It is quite near mint */
  182.             try=(maxt+mint*10)/11;
  183.         } else if(minr*-2<maxr) {
  184.             try=(maxt+mint*2)/3;
  185.         } else
  186.             try=(maxt+mint)/2;
  187.     }
  188.     p->Float=try;
  189.     p->type=TYP_FLT;
  190. }
  191.  
  192. static void
  193. do_fv FUN1(struct value *,p)
  194. {
  195.     double payment    = p->Float;
  196.      double interest = (p+1)->Float;
  197.      double term    = (p+2)->Float;
  198.  
  199.     p->Float = payment * ((pow(1+interest,term)-1)/interest);
  200. }
  201.  
  202. static void
  203. do_rate FUN1(struct value *,p)
  204. {
  205.     double future    = p->Float;
  206.     double present    = (p+1)->Float;
  207.      double term    = (p+2)->Float;
  208.  
  209.     p->Float = pow(future/present,1/term)-1;
  210. }
  211.  
  212. static void
  213. do_term FUN1(struct value *,p)
  214. {
  215.     double payment    = p->Float;
  216.     double interest    = (p+1)->Float;
  217.     double future    = (p+2)->Float;
  218.  
  219.     p->Float = log(1+future*(interest/payment))/log(1+interest);
  220. }
  221.  
  222. static void
  223. do_cterm FUN1(struct value *,p)
  224. {
  225.     double interest    = (p)->Float;
  226.     double future    = (p+1)->Float;
  227.     double present    = (p+2)->Float;
  228.  
  229.     p->Float=log(future/present)/log(1+interest);
  230. }
  231.  
  232. static void
  233. do_sln  FUN1(struct value *,p)
  234. {
  235.     double cost    = (p)->Float;
  236.     double salvage    = (p+1)->Float;
  237.     double life    = (p+2)->Float;
  238.  
  239.     p->Float=(cost-salvage)/life;
  240. }
  241.  
  242. static void
  243. do_syd FUN1(struct value *,p)
  244. {
  245.     double cost,salvage,life,period;
  246.             
  247.     cost=p->Float;
  248.     salvage=(p+1)->Float;
  249.     life=(p+2)->Float;
  250.     period=(p+3)->Float;
  251.     
  252.     if(period>life)        /* JF is this right? */
  253.         p->Float=salvage;
  254.     else
  255.         p->Float=((cost-salvage)*(life-period+1))/(life*((life+1)/2));
  256. }
  257.  
  258.  
  259. static void
  260. do_ddb FUN1(struct value *,p)
  261. {
  262.     double cost    = (p  )->Float;
  263.     double salvage    = (p+1)->Float;
  264.     long life    = (p+2)->Int;
  265.     long period    = (p+3)->Int;
  266.  
  267.     double bookval,tmp;
  268.     long n;
  269.  
  270.     if(period<1 || period>life || life<1) {
  271.         p->Value=OUT_OF_RANGE;
  272.         p->type=TYP_ERR;
  273.         return;
  274.     }
  275.     bookval=cost;
  276.     tmp=0;
  277.     for(n=0;n<period;n++) {
  278.         tmp=(bookval*2)/life;
  279.         bookval-=tmp;
  280.         if(bookval<salvage) {
  281.             tmp+=bookval-salvage;
  282.             bookval=salvage;
  283.         }
  284.     }
  285.     p->Float=tmp;
  286. }
  287.  
  288. static void
  289. do_anrate FUN1(struct value *,p)
  290. {
  291.     double in_pmt    = (p  )->Float;
  292.     double present    = (p+1)->Float;
  293.     double term    = (p+2)->Float;
  294.  
  295.     double tr_lo,tr_hi;
  296.     double mytry;
  297.     double try_pmt;
  298.     int n;
  299.  
  300.     if(in_pmt*term==present) {
  301.         p->Float= 0.0;
  302.         return;
  303.     }
  304.     if(in_pmt*term<present) {
  305.         tr_lo= -1;
  306.         tr_hi=  0;
  307.         while(pmt(present,tr_lo,term)>in_pmt) {
  308.             tr_hi=tr_lo;
  309.             tr_lo*=2;
  310.         }
  311.     } else {
  312.         tr_lo=0;
  313.         tr_hi=1;
  314.         while(pmt(present,tr_hi,term)<in_pmt) {
  315.             tr_lo=tr_hi;
  316.             tr_hi*=2;
  317.         }
  318.     }
  319.     for(n=0;n<40;n++) {
  320.         mytry=(tr_lo+tr_hi)/2;
  321.         try_pmt=pmt(present,mytry,term);
  322.         if(try_pmt<in_pmt)
  323.             tr_lo=mytry;
  324.         else if(try_pmt>in_pmt)
  325.             tr_hi=mytry;
  326.         else
  327.             break;
  328.     }
  329.     p->Float=mytry;
  330. }
  331.  
  332. static void
  333. do_anterm FUN1(struct value *,p)
  334. {
  335.     double payment    = (p  )->Float;
  336.     double principal= (p+1)->Float;
  337.     double rate    = (p+2)->Float;
  338.  
  339.     p->Float = (-log( 1 - principal*(rate/payment)))/log(1+rate);
  340. }
  341.  
  342.  
  343. static void
  344. do_balance FUN1(struct value *,p)
  345. {
  346.     double principal= (p  )->Float;
  347.     double rate    = (p+1)->Float;
  348.     long term    = (p+2)->Int;
  349.      long period    = (p+3)->Int;
  350.  
  351.     double tmp_pmt,int_part;
  352.     long num;
  353.  
  354.     if(term<period) {
  355.         p->Value= OUT_OF_RANGE;
  356.         p->type=TYP_ERR;
  357.         return;
  358.     }
  359.     tmp_pmt=pmt(principal,rate,(double)term);
  360.     for(num=0;num<period;num++) {
  361.         int_part=rate*principal;
  362.         if(int_part>tmp_pmt) {
  363.             p->Value=OUT_OF_RANGE;
  364.             p->type=TYP_ERR;
  365.             return;
  366.         }
  367.         principal-=tmp_pmt-int_part;
  368.     }
  369.     p->Float=principal;
  370. }
  371.  
  372. static void
  373. do_paidint FUN1(struct value *,p)
  374. {
  375.     double principal= (p  )->Float;
  376.     double rate    = (p+1)->Float;
  377.     long term    = (p+2)->Int;
  378.     long period    = (p+3)->Int;
  379.  
  380.     double tmp_pmt, int_part, retval;
  381.     long num;
  382.  
  383.     if(term<period) {
  384.         p->Value= OUT_OF_RANGE;
  385.         p->type=TYP_ERR;
  386.         return;
  387.     }
  388.     tmp_pmt=pmt(principal,rate,(double)term);
  389.     retval=0;
  390.     for(num=0;num<period;num++) {
  391.         int_part=rate*principal;
  392.         if(int_part>tmp_pmt) {
  393.             p->Value= OUT_OF_RANGE;
  394.             p->type=TYP_ERR;
  395.             return;
  396.         }
  397.         principal-=tmp_pmt-int_part;
  398.         retval+=int_part;
  399.     }
  400.     p->Float=retval;
  401. }
  402.  
  403. static void
  404. do_kint FUN1(struct value *,p)
  405. {
  406.     double principal=(p  )->Float;
  407.     double rate    =(p+1)->Float;
  408.     long term    =(p+2)->Int;
  409.     long period    =(p+3)->Int;
  410.  
  411.     double tmp_pmt, int_part = 0;
  412.     long num;
  413.  
  414.     if(term<period) {
  415.         p->Value= OUT_OF_RANGE;
  416.         p->type=TYP_ERR;
  417.         return;
  418.     }
  419.             
  420.     tmp_pmt=pmt(principal,rate,(double)term);
  421.     for(num=0;num<period;num++) {
  422.         int_part=rate*principal;
  423.         if(int_part>tmp_pmt) {
  424.             p->Value= OUT_OF_RANGE;
  425.             p->type=TYP_ERR;
  426.             return;
  427.         }
  428.         principal-=tmp_pmt-int_part;
  429.     }
  430.     p->Float=int_part;
  431. }
  432.  
  433. static void
  434. do_kprin FUN1(struct value *,p)
  435. {
  436.     double principal=(p  )->Float;
  437.     double rate    =(p+1)->Float;
  438.     long term    =(p+2)->Int;
  439.     long period    =(p+3)->Int;
  440.     double tmp_pmt, int_part=0;
  441.     long num;
  442.  
  443.     if(term<period) {
  444.         p->Value= OUT_OF_RANGE;
  445.         p->type=TYP_ERR;
  446.         return;
  447.     }
  448.  
  449.     tmp_pmt=pmt(principal,rate,(double)term);
  450.     for(num=0;num<period;num++) {
  451.         int_part=rate*principal;
  452.         if(int_part>tmp_pmt) {
  453.             p->Value= OUT_OF_RANGE;
  454.             p->type=TYP_ERR;
  455.             return;
  456.         }
  457.         principal-=tmp_pmt-int_part;
  458.     }
  459.     p->Float=tmp_pmt-int_part;
  460. }
  461.  
  462. static void
  463. do_compbal FUN1(struct value *,p)
  464. {
  465.     double principal= (p  )->Float;
  466.     double rate    = (p+1)->Float;
  467.     double term    = (p+2)->Float;
  468.  
  469.     p->Float = principal * pow(1+rate,term);
  470. }
  471.  
  472. struct function busi_funs[] = {
  473. { C_FN2,    X_A2,        "RF",   do_npv,    "npv" },
  474. { C_FN2,    X_A2,        "RF",   do_irr,    "irr" },
  475.  
  476. { C_FN3,    X_A3,        "FFF",  do_pmt,    "pmt" },
  477. { C_FN3,    X_A3,        "FFF",  do_pv,    "pv" },
  478. { C_FN3,    X_A3,        "FFF",  do_fv,    "fv" },
  479. { C_FN3,    X_A3,        "FFF",  do_rate,    "rate" },
  480. { C_FN3,    X_A3,        "FFF",  do_term,    "term" },
  481. { C_FN3,    X_A3,        "FFF",  do_cterm,    "cterm" },
  482. { C_FN3,    X_A3,        "FFF",  do_sln,    "sln" },
  483. { C_FN3,    X_A3,        "FFF",  do_anrate,    "anrate" },
  484. { C_FN3,    X_A3,        "FFF",  do_anterm,    "anterm" },
  485. { C_FN3,    X_A3,        "FFF",  do_compbal,    "compbal" },
  486.  
  487. { C_FN4,    X_A4,        "FFFF", do_syd,    "syd" },
  488. { C_FN4,    X_A4,        "FFII", do_ddb,    "ddb" },
  489. { C_FN4,    X_A3,        "FFII", do_balance,    "balance" },
  490. { C_FN4,    X_A4,        "FFII", do_paidint,    "paidint" },
  491. { C_FN4,    X_A4,        "FFII", do_kint,    "kint" },
  492. { C_FN4,    X_A4,        "FFII", do_kprin,    "kprin" },
  493.  
  494. { 0,        0,        "",        0,         0 },
  495. };
  496.  
  497.